package com.bph.schedule.service.impl;

import com.bph.commons.pojo.Message;
import com.bph.commons.pojo.User;
import com.bph.commons.pojo.User_Preference;
import com.bph.commons.utils.SP;
import com.bph.commons.utils.TotalDays;
import com.bph.commons.vo.ResultVo;
import com.bph.schedule.algorithm.Data;
import com.bph.schedule.algorithm.ScheduleHandler;
import com.bph.schedule.mapper.ScheduleMapper;
import com.bph.schedule.service.ScheduleService;
import com.sun.jersey.server.impl.model.parameter.multivalued.StringReaderProviders;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.*;
import java.util.stream.Collectors;


@Service
public class ScheduleServiceImpl implements ScheduleService {
    @Resource
    private ScheduleMapper scheduleMapper;

    //根据员工id获得排班信息
    @Override
    public ResultVo selectMessageByUserId(User user) {
        /**
         * 得到该员工信息表的数据
         */
        List<Message>  messageList1 = scheduleMapper.selectEmployeeListByUserId(Integer.toString(user.getUser_id()));
        System.out.println(messageList1);

        if(messageList1.size() == 0){
            return ResultVo.getFailVo("获取排班列表失败",2);
        }


        /**
         * 创建dayList、weekList、monthList
         * 特殊处理：该员工班次第一周的情况和最后一周的情况
         */
        int firstEmpty = messageList1.get(0).getMessage_startTime().toLocalDateTime().getDayOfWeek().getValue()-1;
        int lastEmpty = 7-messageList1.get(messageList1.size()-1).getMessage_startTime().toLocalDateTime().getDayOfWeek().getValue();
        ArrayList<String> dayList = new ArrayList<>(6);
        //dayList0元素为6个空字符串，只做占位作用
        ArrayList<String> dayList0 = new ArrayList<>(6);
        for(int i=1; i<=6; i++){
            dayList0.add("");
        }
        ArrayList weekList = new ArrayList<>(), monthList = new ArrayList<>();
        for(int i=1; i<=firstEmpty; i++){
            weekList.add(dayList0);
        }


        /**
         * 遍历该员工的排班信息表
         * 根据message_id是否相邻合并时间段，录入dayList中，再将dayList录入weekList中
         * weekList元素满7个录入monthList中
         * 期间进行各种特殊情况的处理
         */
        double start = 0;
        double finish = 0;
        for(int i=1; i<=6; i++){
            dayList.add("");
        }
        for(Message message:messageList1){
            if(messageList1.indexOf(message) == 0){
                start = message.getMessage_startTime().toLocalDateTime().getHour() + (double)message.getMessage_startTime().toLocalDateTime().getMinute()/60;
            }
            else {
                Message message0 = messageList1.get(messageList1.indexOf(message) - 1);
                if ((message.getMessage_startTime().toLocalDateTime().getDayOfMonth() != message0.getMessage_startTime().toLocalDateTime().getDayOfMonth()) || (message.getMessage_id() - message0.getMessage_id() != 1)) {

                    start = message.getMessage_startTime().toLocalDateTime().getHour() + (double)message.getMessage_startTime().toLocalDateTime().getMinute() / 60;

                }
            }
            if(messageList1.indexOf(message) == messageList1.size()-1){
                finish = message.getMessage_finishTime().toLocalDateTime().getHour() + (double)message.getMessage_finishTime().toLocalDateTime().getMinute()/60;
                String s = ""+start+","+finish+"";
                if(start <= 12){
                    if(dayList.get(0).equals("")){
                        dayList.set(0,s);
                    }
                    else {
                        dayList.set(1,s);
                    }
                }
                if(12 < start && start <= 18){
                    if(dayList.get(2).equals("")){
                        dayList.set(2,s);
                    }
                    else {
                        dayList.set(3,s);
                    }
                }
                if( start > 18){
                    if(dayList.get(4).equals("")){
                        dayList.set(4,s);
                    }
                    else {
                        dayList.set(5,s);
                    }
                }
                ArrayList<String> dayList1 = (ArrayList<String>) dayList.clone();
                weekList.add(dayList1);
                for(int i=1; i<=lastEmpty; i++){
                    weekList.add(dayList0);

                }
                ArrayList weekList1 = (ArrayList) weekList.clone();
                monthList.add(weekList1);

                //使weekList中的dayList为空字符串
                weekList.clear();
                for(int i=1; i<=7; i++){
                    weekList.add(dayList0);
                }

                //得到本月的总天数，引入TotalDays工具类
                int totalDays = TotalDays.totalDays(message.getMessage_finishTime().toLocalDateTime().getMonth().getValue(),message.getMessage_finishTime().toLocalDateTime().getYear());

                //找到该用户最后一条数据日期的周末
                int finishWeekend = message.getMessage_finishTime().toLocalDateTime().getDayOfMonth()+lastEmpty;
                if(finishWeekend < totalDays){
                    int emptyWeek;
                    int emptyDay = (totalDays-finishWeekend) % 7;
                    if(emptyDay != 0){
                        emptyWeek = (totalDays-finishWeekend) / 7 + 1;
                    }
                    else {
                        emptyWeek= (totalDays-finishWeekend) / 7;
                    }
                    for(int i=1; i<=emptyWeek; i++){
                        ArrayList weekList0 = (ArrayList) weekList.clone();
                        monthList.add(weekList0);
                    }
                }
            }
            else {
                Message message1 = messageList1.get(messageList1.indexOf(message) + 1);
                if ((message.getMessage_startTime().toLocalDateTime().getDayOfMonth() != message1.getMessage_startTime().toLocalDateTime().getDayOfMonth()) || (message1.getMessage_id() - message.getMessage_id() != 1)) {
                    finish = message.getMessage_finishTime().toLocalDateTime().getHour() + (double)message.getMessage_finishTime().toLocalDateTime().getMinute() / 60;
                    String s = "" + start + "," + finish + "";
                    if (start <= 12) {
                        if (dayList.get(0).equals("")) {
                            dayList.set(0, s);
                        } else {
                            dayList.set(1, s);
                        }
                    }
                    if (12 < start && start <= 18) {
                        if (dayList.get(2).equals("")) {
                            dayList.set(2, s);
                        } else {
                            dayList.set(3, s);
                        }
                    }
                    if (start > 18) {
                        if (dayList.get(4).equals("")) {
                            dayList.set(4, s);
                        } else {
                            dayList.set(5, s);
                        }
                    }
                    int count = message1.getMessage_startTime().toLocalDateTime().getDayOfMonth() - message.getMessage_startTime().toLocalDateTime().getDayOfMonth();
                    if (count >= 1) {
                        ArrayList<String> dayList1 = (ArrayList<String>) dayList.clone();
                        weekList.add(dayList1);

                        if (weekList.size() == 7) {
                            ArrayList weekList1 = (ArrayList) weekList.clone();
                            monthList.add(weekList1);
                            weekList.clear();
                        }
                        dayList.clear();
                        for (int i = 1; i <= 6; i++) {
                            dayList.add("");
                        }
                        for (int i = 0; i < count - 1; i++) {
                            weekList.add(dayList0);

                            if (weekList.size() == 7) {
                                ArrayList weekList1 = (ArrayList) weekList.clone();
                                monthList.add(weekList1);
                                weekList.clear();
                            }

                        }
                    }
                }
            }
        }

        return ResultVo.getSuccessVo("获取排班列表成功",monthList);
    }

    //获取所有时间段员工的排班信息
    @Override
    public ResultVo getAllSchedule() {
        //查询信息表的message_id,message_startTime,message_finishTime,employeeList列
        List<Message> messageList = scheduleMapper.selectMessage();
        List dayList = new ArrayList();
        List dayList0 = new ArrayList();
        List timeList = new ArrayList();//存储每天的timeMap，放在周天后,所以WeekList.size()==8
        Map timeMap = new HashMap();//存储每天的开班时间和下班时间

        Map timeMap0 = new HashMap();//占位，用于不属于本月的日期
        timeMap0.put("startTime",null);
        timeMap0.put("finishTime",null);

        List weekList = new ArrayList();
        List monthList = new ArrayList();
        for(Message message:messageList){
            //起始数据，判断星期几，记录这一天的开始时间
            if(messageList.indexOf(message) == 0){
                int firstEmpty = message.getMessage_startTime().toLocalDateTime().getDayOfWeek().getValue() - 1;
                for(int i = 1; i <= firstEmpty; i++){
                    weekList.add(dayList0);
                    timeList.add(timeMap0);
                }
                timeMap.put("startTime",message.getMessage_startTime().toLocalDateTime().getHour());
            }
            //下一天的第一个数据
            else if(messageList.get(messageList.indexOf(message) - 1).getMessage_finishTime().toLocalDateTime().getDayOfMonth()
                    != message.getMessage_finishTime().toLocalDateTime().getDayOfMonth()){
                timeMap.put("startTime",message.getMessage_startTime().toLocalDateTime().getHour());
            }

            //在一个时间段的最后一个点（偶数点），查找员工信息，存入时间段列表hourList
            if((message.getMessage_id())%2 == 0) {
                List hourList = new ArrayList();
                //获得时间段前后两个带“,”的employeeList字符串,转化为List
                String front = messageList.get(messageList.indexOf(message) - 1).getEmployeeList();
                List<String> frontSplit = new ArrayList<>();
                String back = message.getEmployeeList();
                List<String> backSplit = new ArrayList<>();

                if(front == null){
                    frontSplit = null;
                }
                else{
                    frontSplit = Arrays.asList(front.split(","));
                }
                if (back ==null){
                    backSplit = null;
                }
                else{
                    backSplit = Arrays.asList(back.split(","));
                }

                //利用JDK的Arrays类,将两个带“,”的employeeList字符串合并，转化为List
                List<String> split1 = Arrays.asList((front + "," + back).split(","));
                //使用stream方法去重
                List<String> split = split1.stream().distinct().collect(Collectors.toList());
                for (String strId : split) {
                    if(!strId.equals("null")){
                        Map userMap1 = scheduleMapper.getUserByUserId(Integer.parseInt(strId));
                        if(frontSplit != null && frontSplit.contains(strId)){
                            if(backSplit != null && backSplit.contains(strId)){
                                userMap1.put("user_shift", 3);
                            }
                            else{
                                userMap1.put("user_shift", 1);
                            }
                        }
                        else{
                            userMap1.put("user_shift", 2);
                        }
                        hourList.add(userMap1);
                    }
                }
                dayList.add(hourList);


                //特殊情况:最后一条数据
                if(messageList.indexOf(message) + 1 == messageList.size()){
                    int lasyEmpty = 7-message.getMessage_startTime().toLocalDateTime().getDayOfWeek().getValue();
                    List dayList1 = new ArrayList(dayList);
                    weekList.add(dayList1);
                    dayList.clear();
                    for(int i = 1; i <= lasyEmpty; i++){
                        weekList.add(dayList0);
                    }
                    timeMap.put("finishTime",message.getMessage_finishTime().toLocalDateTime().getHour());
                    Map timeMap1 = new HashMap(timeMap);
                    timeList.add(timeMap1);
                    timeMap.clear();
                    for(int i = 1; i <= lasyEmpty; i++){
                        timeList.add(timeMap0);
                    }

                    List timeList1 = new ArrayList(timeList);
                    weekList.add(timeList1);
                    timeList.clear();

                    List weekList1 = new ArrayList(weekList);
                    monthList.add(weekList1);
                    weekList.clear();
                }
                //一天的最后一个数据（不是最后一天），将一天的数据存入weekList，清空dayList
                else if(messageList.get(messageList.indexOf(message) + 1).getMessage_finishTime().toLocalDateTime().getDayOfMonth()
                        != message.getMessage_finishTime().toLocalDateTime().getDayOfMonth()){
                    timeMap.put("finishTime",message.getMessage_finishTime().toLocalDateTime().getHour());
                    Map timeMap1 = new HashMap(timeMap);
                    timeList.add(timeMap1);
                    timeMap.clear();
                    //若是星期天则将timeList存入，并将weekList存入monthList
                    if(weekList.size() == 7){
                        List timeList1 = new ArrayList(timeList);
                        weekList.add(timeList1);
                        timeList.clear();

                        List weekList1 = new ArrayList(weekList);
                        monthList.add(weekList1);
                        weekList.clear();
                    }
                    List dayList1 = new ArrayList(dayList);
                    weekList.add(dayList1);
                    dayList.clear();
                }
            }
        }
        return ResultVo.getSuccessVo("获取员工排班信息成功", monthList);
    }



    //店长生成一个月的排班表
    public ResultVo schedule(int store_id,int month){

        String m = String.valueOf(month);
        //先从数据库中获取 一周的 客流业务预测数据
        List<LinkedHashMap<String,Object>> customerFlow = scheduleMapper.getCustomerFlowByStoreId(store_id,m);
        //处理业务预测数据得出7天的实际班次需求
        ArrayList<LinkedHashMap<String, Integer>> scheduleRequired = Data.scheduleRequired(customerFlow);

        //生成员工数据表
        ArrayList<LinkedHashMap<String,Object>> employeesInfo = new ArrayList<>();
        //先查门店所有员工的信息
        List<User> userList = scheduleMapper.getUserByStoreId(store_id);

        for(User user:userList){
            int user_id = user.getUser_id();
            LinkedHashMap<String,Object> upref = new LinkedHashMap<>();//存偏好
            //查询员工偏好
            List<User_Preference> userPreferences = scheduleMapper.getUPreferenceByUid(user_id);
            if(userPreferences != null){
                for (User_Preference up : userPreferences) {
                    int pId = up.getPreference_id();
                    String pValue = up.getUser_preference_value();
                    if (pId == 3) {//时间偏好
                        upref.put("pStage", pValue);
                    } else if (pId == 2) {
                        upref.put("pTime", pValue);
                    } else {
                        upref.put("pSex", pValue);
                    }
                }
                //为没有的偏好设置默认值
                upref.putIfAbsent("pStage", "8,22");
                upref.putIfAbsent("pTime", "2,4");
                upref.putIfAbsent("pSex","2");
            }
            else{//什么偏好都没有也设为默认偏好
                upref.put("pStage","8,22");
                upref.put("pTime","2,4");
                upref.put("pSex","2");
            }

            employeesInfo.add(Data.employeeInfo(user,upref));
        }
        Data.EmployeeInfo = employeesInfo;

        //去排班
        LinkedHashMap<String, ArrayList<User>> monthSchedule
                = ScheduleHandler.schedule(scheduleRequired,employeesInfo);
        //写入数据库
        for(String time: monthSchedule.keySet()){
            if(!("开放班次".equals(monthSchedule.get(time).get(0).getUser_name()))){
                String start_time = SP.str_Parse(time)[0];
                String employeeList = "";
                for(User user:monthSchedule.get(time)){
                    employeeList += user.getUser_id()+",";
                }
                employeeList = employeeList.substring(0,employeeList.length()-1);
                scheduleMapper.addScheduleByStoreId(employeeList,start_time);
            }
        }

        ResultVo vo = new ResultVo();
        vo.setS_code(200);
        String message = "排班成功！无开放班次√";
        if(ScheduleHandler.empty != null) {
            message = "排班成功!部分班次未匹成功！";
            vo.setR_data(ScheduleHandler.empty);
        }else{
            vo.setR_data("happy");
        }
        vo.setE_message(message);
        return vo;
    }
}
